/*
 * Lua 5.1 grammar
 * 
 * Nicolai Mainiero
 * May 2007
 * 
 * This is a Lua (http://www.lua.org) grammar for the version 5.1 for ANTLR 3.
 * I tested it with basic and extended examples and it worked fine. It is also used
 * for LunarEclipse (http://lunareclipse.sf.net) a Lua editor based on Eclipse.
 * 
 * Thanks to Johannes Luber and Gavin Lambert who helped me with some mutually left recursion.
 *  
 */

grammar Lua;

chunk : (stat (';')?)* (laststat (';')?)?;

block : chunk;

stat :  varlist1 '=' explist1 | 
	functioncall | 
	'do' block 'end' | 
	'while' exp 'do' block 'end' | 
	'repeat' block 'until' exp | 
	'if' exp 'then' block ('elseif' exp 'then' block)* ('else' block)? 'end' | 
	'for' NAME '=' exp ',' exp (',' exp)? 'do' block 'end' | 
	'for' namelist 'in' explist1 'do' block 'end' | 
	'function' funcname funcbody | 
	'local' 'function' NAME funcbody | 
	'local' namelist ('=' explist1)? ;

laststat : 'return' (explist1)? | 'break';

funcname : NAME ('.' NAME)* (':' NAME)? ;

varlist1 : var (',' var)*;


namelist : NAME (',' NAME)*;

explist1 : (exp ',')* exp;

exp :  ('nil' | 'false' | 'true' | number | string | '...' | function | prefixexp | tableconstructor | unop exp) (binop exp)* ;

var: (NAME | '(' exp ')' varSuffix) varSuffix*;

prefixexp: varOrExp nameAndArgs*;

functioncall: varOrExp nameAndArgs+;

/*
var :  NAME | prefixexp '[' exp ']' | prefixexp '.' NAME; 

prefixexp : var | functioncall | '(' exp ')';

functioncall :  prefixexp args | prefixexp ':' NAME args ;
*/

varOrExp: var | '(' exp ')';

nameAndArgs: (':' NAME)? args;

varSuffix: nameAndArgs* ('[' exp ']' | '.' NAME);

args :  '(' (explist1)? ')' | tableconstructor | string ;

function : 'function' funcbody;

funcbody : '(' (parlist1)? ')' block 'end';
parlist1 : namelist (',' '...')? | '...';
tableconstructor : '{' (fieldlist)? '}';

fieldlist : field (fieldsep field)* (fieldsep)?;
field : '[' exp ']' '=' exp | NAME '=' exp | exp;
fieldsep : ',' | ';';
binop : '+' | '-' | '*' | '/' | '^' | '%' | '..' | 
		 '<' | '<=' | '>' | '>=' | '==' | '~=' | 
		 'and' | 'or';
unop : '-' | 'not' | '#';
number : INT | FLOAT | EXP | HEX;
string	: NORMALSTRING | CHARSTRING | LONGSTRING;


// LEXER

NAME	:('a'..'z'|'A'..'Z'|'_')(options{greedy=true;}:	'a'..'z'|'A'..'Z'|'_'|'0'..'9')*
	;
INT	: ('0'..'9')+;
FLOAT 	:INT '.' INT ;
EXP	: (INT| FLOAT) ('E'|'e') ('-')? INT;
HEX	:'0x' ('0'..'9'| 'a'..'f')+ ;

	

NORMALSTRING
    :  '"' ( EscapeSequence | ~('\\'|'"') )* '"' 
    ;

CHARSTRING
   :	'\'' ( EscapeSequence | ~('\''|'\\') )* '\''
   ;

LONGSTRING
	:	'['('=')*'[' ( EscapeSequence | ~('\\'|']') )* ']'('=')*']'
	;

fragment
EscapeSequence
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UnicodeEscape
    |   OctalEscape
    ;
    
fragment
OctalEscape
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;
    
fragment
UnicodeEscape
    :   '\\' 'u' HexDigit HexDigit HexDigit HexDigit
    ;
    
fragment
HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ;


COMMENT
    :   '--[[' ( options {greedy=false;} : . )* ']]' {skip();}
    ;
    
LINE_COMMENT
    : '--' ~('\n'|'\r')* '\r'? '\n' {skip();}
    ;
    
    
WS  :  (' '|'\t'|'\u000C') {skip();}
    ;
    
NEWLINE	: ('\r')? '\n' {skip();}
	;

// FIM DE ARQUIVO

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

 grammar Lua;
 
 //Palavras chaves da linguagem
 AND      : 'and';
 BREAK    : 'break';
 DO       : 'do';
 ELSE     : 'else';
 ELSEIF   : 'elseif';
 END      : 'end';
 FALSE    : 'false';
 FOR      : 'for';
 FUNCTION : 'function';
 IF       : 'if';
 IN       : 'in'; 
 LOCAL    : 'local';
 NIL      : 'nil';
 NOT      : 'not'; 
 OR       : 'or';
 REPEAT   : 'repeat';
 RETURN   : 'return';
 THEN     : 'then';
 TRUE     : 'true';
 UNTIL    : 'until';
 WHILE    : 'while';
 
 //SEPARADORDECAMPOS : ',' | ';';
 
 //SEPARADORCOMANDO : ';';
 
 PONTO : '.';
 
 fragment
 MENOS : '-';
 
 OPUNARIA : MENOS | NOT | '#';

 OPBIN : '+' | MENOS | '*' | '/' | '^' | '%' | '..' |
         '<' | '<=' | '>' | '>=' | '==' | '~=' |
         AND | OR; 

 APAREN : '(';
 FPAREN : ')';
 ACOLC : '[';
 FCOLC : ']';
 ACHAVE : '{';
 FCHAVE : '}';
 
 //CADEIA de caracteres 
 CADEIA: '\'' (~('\''|'\\'))* '\'' ;
 
  //NOMEs na linguagem
 NOME : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*;
 
  //Contantes numericas
 NUMERO : (('0'..'9')+ '.' ('0'..'9')+ | ('0'..'9')+ );
 
  //Simbolos desconsiderados
 COMENTARIO : '--' .*? '\n' {skip();};
 ESPACO: (' '|'\t'|'\r'|'\n') {skip();};
  
 
 /*
 //Palavras chaves da linguagem
 Pchave : 'and'| 'break'| 'do' | 'else' | 'elseif' | 
           'end'| 'false'| 'for' | 'function' | 'if'| 'in'| 
           'local' | 'nil' | 'not' | 'or' | 'reapeat' | 'return' |
           'then' | 'true' | 'until' | 'while';
 
  //Simbolos reservados da liguagem
 Sreservado : '+'|'-'|'*'|'/'|'%'|'^'|'=='|'<='|'>='|
             '>'|'<'|'='|'('|')'|'{'|'}'|'['|']'|';'|':'|','|'.'|'..'|'...';

*/
 
  //Analisador Sintático

programa : trecho;
bloco    : trecho;
trecho   : (comando (';')?)* (ultimocomando (';')?)?;


comando : listavar '=' listaexp | expprefixo2 | DO bloco END |
          WHILE exp DO bloco END | REPEAT bloco UNTIL exp |
          IF exp THEN bloco (ELSEIF exp THEN bloco)* (ELSE bloco)? END |
          FOR NOME '=' exp ',' exp (',' exp)? DO bloco END |
          FOR listadenomes IN listaexp DO bloco END |
          FUNCTION nomedafuncao corpodafuncao |
          LOCAL FUNCTION NOME corpodafuncao |
          LOCAL listadenomes ('=' listaexp)?;

ultimocomando : RETURN (listaexp)? | BREAK;
nomedafuncao  : NOME ('.' NOME)* (':' NOME)?;
listavar      : var (',' var)*;
//var2           : NOME | expprefixo ACOLC exp FCOLC | expprefixo '.' NOME;
var : expprefixo2;
listadenomes  : NOME (',' NOME)*;
listaexp      : (exp ',')* exp;

exp : NIL | FALSE | TRUE | NUMERO | CADEIA | '...' | funcao |
      expprefixo2 | construtortabela | exp OPBIN exp | OPUNARIA exp;

//expprefixo       : var | chamadadefuncao | APAREN exp FPAREN;
expprefixo2        : (NOME ( ACOLC exp FCOLC | '.' NOME )* (args | ':' NOME args)?) | APAREN exp FPAREN;
//chamadadefuncao   : expprefixo args | expprefixo ':' NOME args;
args              : APAREN (listaexp)? FPAREN | construtortabela | CADEIA;
funcao            : FUNCTION corpodafuncao;
corpodafuncao     : APAREN (listapar)? FPAREN bloco END;
listapar          : listadenomes (',' '...')? | '...';
construtortabela  : ACHAVE (listadecampos)? FCHAVE;
listadecampos     : campo ((',' | ';') campo)* (',' | ';')?;
campo             : ACOLC exp FCOLC '=' exp | NOME '=' exp | exp;

/*

programa : trecho;
trecho   : (comando (SeparadorComando)?)* (ultimocomando (SeparadorComando)?)?;
bloco    : trecho;

comando : listavar '=' listaexp | chamadadefuncao | do bloco end |
          while exp do bloco end | repeat bloco until exp |
          if exp then bloco (elseif exp then bloco)* (else bloco)? end |
          for NOME '=' exp ',' exp (',' exp)? do bloco end |
          for listadenomes in listaexp do bloco end |
          function nomedafuncao corpodafuncao |
          local function NOME corpodafuncao |
          local listadenomes ('=' listaexp)?;

ultimocomando : return (listaexp)? | break;
nomedafuncao  : NOME ('.' NOME)* (':' NOME)?;
listavar      : var (',' var)*;
var           : NOME | expprefixo '[' exp ']' | expprefixo '.' NOME;
listadenomes  : NOME (',' NOME)*;
listaexp      : (exp ',')* exp;

exp : nil | false | true | NUMERO | CADEIA | '...' | funcao |
      expprefixo | construtortabela | exp opbin exp | opunaria exp;

expprefixo        : var | chamadadefuncao | '(' exp ')'
chamadadefuncao   : expprefixo args | expprefixo ':' NOME args;
args              : '(' (listaexp)? ')' | construtortabela | CADEIA;
funcao            : function corpodafuncao;
corpodafuncao     : '(' (listapar)? ')' bloco end;
listapar          : listadenomes (',' '...')? | '...';
construtortabela  : '{' (listadecampos)? '}';
listadecampos     : campo (separadordecampos campo)* (separadordecampos)?;
campo             : '[' exp ']' '=' exp | NOME '=' exp | exp;
separadordecampos : ',' | ';';

opbin : '+' | '-' | '*' | '/' | '^' | '%' | '..' |
        '<' | '<=' | '>' | '>=' | '==' | '~=' |
        and | or;

opunaria : '-' | not | '#';

*/